feat(security): add XSS sanitization and security headers#1455
feat(security): add XSS sanitization and security headers#1455kelvinkipruto wants to merge 6 commits intomainfrom
Conversation
- Sanitize user-provided embed HTML with xss library - Add Content-Security-Policy and other security headers - Normalize CORS/CSRF origins and set default allowed origin - Update HelplineCard, RowCard, and ActionBanner components to use sanitized embed code
|
It's cool to sanitize @kelvinkipruto if it's not a lot of work. Remember, we're not getting content from end users i.e. the web like reddit. We're rendering content from a CMS managed and reviewed by trusted content editors. |
|
Claude finished @kelvinkipruto's task in 2m 1s —— View job PR Review: feat(security): add XSS sanitization and security headers
Overall this is a solid, well-structured security PR. I have a few issues of varying severity to flag.
|
| Severity | Issue |
|---|---|
| Medium | iframe.src in sanitizer lacks protocol validation |
| Medium | HelplineEmbedDialog doesn't sanitize its own input |
| Low | CSP script-src 'unsafe-inline' https: is very broad |
| Low | sandbox not enforced on iframes |
| Info | securityHeaders module-level constant evaluated at import |
| ✓ | payload.config.ts refactor is a clear improvement |
| ✓ | Security headers are a welcome addition |
My question still remains @kelvinkipruto , why go through all of this if the content comes from our CMS which we have full control of? The content doesn't come from the wild web out there. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a99adb6537
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (nodeEnv === "production") { | ||
| // HSTS is intentionally production-only so local HTTP development and | ||
| // non-TLS preview setups do not get sticky HTTPS behavior. | ||
| headers.push({ | ||
| key: "Strict-Transport-Security", |
There was a problem hiding this comment.
Guard HSTS behind explicit TLS deployment flag
Strict-Transport-Security is currently enabled whenever NODE_ENV === "production", but production mode is commonly used for HTTP-only preview/staging deployments too. In those environments, sending HSTS causes browsers to cache an HTTPS-only policy for the host, which can make the preview site inaccessible and persists beyond a single session. Since this code intends to avoid non-TLS preview stickiness, it should be gated by an explicit HTTPS/TLS deployment signal rather than NODE_ENV alone.
Useful? React with 👍 / 👎.
Description
Fixes # (issue)
Type of change
Screenshots
Checklist: